//
// CDVCaptureFilter.cpp
//

#include "stdafx.h"
#include "CDVCaptureFilter.h"

#include "GlobalDefs.h"
#include "UDsUtils.h"
#include "xprtdefs.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

////////////////////////////////////////////////////////////////////////
CDVCaptureFilter::CDVCaptureFilter(IGraphBuilder * inGraph, 
								   const char * inDeviceName) 
: CDXFilter(inGraph, GUID_NULL, "DV Capture")
{
	if (inDeviceName)
	{
		strcpy(mDeviceName, inDeviceName);
	}

	mDevice     = NULL;
	mTransport  = NULL;
	mTimeReader = NULL;
}

CDVCaptureFilter::~CDVCaptureFilter(void)
{
	ReleaseFilter();
}

BOOL CDVCaptureFilter::CreateFilter(void)
{
	if (mFilter)
	{
		return TRUE;
	}

	if (mGraph)
	{
		mFilter = UDsUtils::CreateVideoDevice(mDeviceName);
		if (mFilter)
		{
			// Get some interfaces
			mFilter->QueryInterface(IID_IAMExtTransport, (void **)&mTransport);
			mFilter->QueryInterface(IID_IAMExtDevice, (void **)&mDevice);
			mFilter->QueryInterface(IID_IAMTimecodeReader, (void **)&mTimeReader);	

			if (SUCCEEDED(mGraph->AddFilter(mFilter, mName)))
			{
				return TRUE;
			}
		}
	}

	ReleaseFilter();
	return FALSE;
}

void CDVCaptureFilter::ReleaseFilter(void)
{
	SAFE_RELEASE(mDevice);
	SAFE_RELEASE(mTransport);
	SAFE_RELEASE(mTimeReader);

	CDXFilter::ReleaseFilter();
}

IPin * CDVCaptureFilter::GetAVOutputPin(void)
{
	return CDXFilter::GetPin(FALSE, "DV A/V Out");
}

IPin * CDVCaptureFilter::GetVideoOutputPin(void)
{
	return CDXFilter::GetPin(FALSE, "DV Vid Out");
}

BOOL CDVCaptureFilter::IsVCR(void)
{
	if (mDevice)
	{
		long   value1 = 0;
		double value2 = 0;
		HRESULT hr = mDevice->GetCapability(ED_DEVCAP_DEVICE_TYPE, 
			&value1, &value2);
		return (value1 == ED_DEVTYPE_VCR);
	}
	return FALSE;
}

BOOL CDVCaptureFilter::IsPAL(void)
{
	if (mTransport)
	{
		long videoType = 0;
		if (SUCCEEDED(mTransport->GetTransportBasicParameters(ED_TRANSBASIC_OUTPUT_SIGNAL, 
			&videoType, NULL)))
		{
			if (videoType == ED_TRANSBASIC_SIGNAL_625_50_SD ||
				videoType == ED_TRANSBASIC_SIGNAL_625_50_SD)
			{
				return TRUE;
			}
		}
	}
	return FALSE;
}

BOOL CDVCaptureFilter::Play(void)
{
	if (mTransport && IsVCR())
	{
		if (SUCCEEDED(mTransport->put_Mode(ED_MODE_PLAY)))
		{
			long mode     = 0;
			long tryTimes = 0;

			mTransport->get_Mode(&mode);
			// Wait for mode-switching finished
			while (mode != ED_MODE_PLAY)
			{
				Sleep(100);
				mTransport->get_Mode(&mode);
				if (++tryTimes >= 100)
				{
					break;
				}
			}
			return TRUE;
		}
	}

	return FALSE;
}

BOOL CDVCaptureFilter::Stop(void)
{
	if (mTransport && IsVCR())
	{
		if (SUCCEEDED(mTransport->put_Mode(ED_MODE_STOP)))
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDVCaptureFilter::Pause(void)
{
	if (mTransport && IsVCR())
	{
		if (SUCCEEDED(mTransport->put_Mode(ED_MODE_FREEZE)))
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDVCaptureFilter::FastForward(void)
{
	if (mTransport && IsVCR())
	{
		if (SUCCEEDED(mTransport->put_Mode(ED_MODE_FF)))
	//	if (SUCCEEDED(mTransport->put_Mode(ED_MODE_PLAY_FASTEST_FWD)))
		{
			return TRUE;
		}
	}
	return FALSE;
}

BOOL CDVCaptureFilter::Rewind(void)
{
	if (mTransport && IsVCR())
	{
		if (SUCCEEDED(mTransport->put_Mode(ED_MODE_REW)))
	//	if (SUCCEEDED(mTransport->put_Mode(ED_MODE_PLAY_FASTEST_REV)))
		{
			return TRUE;
		}
	}
	return FALSE;
}

long CDVCaptureFilter::GetMode(void)
{
	long mode = 0;
	if (mTransport)
	{		
		HRESULT hr = mTransport->get_Mode(&mode);
	}
	return mode;
}

BOOL CDVCaptureFilter::GetTimeCode(void)
{
	if (!mTimeReader)
	{
		return FALSE;
	}

	TIMECODE_SAMPLE  timecodeSample;
	timecodeSample.timecode.dwFrames = 0;
	timecodeSample.dwFlags = ED_DEVCAP_TIMECODE_READ;

	// Query the TimeCode sample data
	HRESULT hr = mTimeReader->GetTimecode(&timecodeSample);
	if (SUCCEEDED(hr))
	{
		// Hour
		long hour   = (timecodeSample.timecode.dwFrames & 0xff000000) >> 24;
		// Minute
		long minute = (timecodeSample.timecode.dwFrames & 0x00ff0000) >> 16;
		// Second
		long second = (timecodeSample.timecode.dwFrames & 0x0000ff00) >>  8;
		// Frame
		long frame  = timecodeSample.timecode.dwFrames & 0x000000ff;
	}
	return SUCCEEDED(hr);
}